/*
Copyright (c) 2011 ATTi 
All rights reserved.
Author: Michael Shu
Purpose : Custom Case Clone function, clone Attachments and Case Comments.
Project : CCIR
Date: 5/25/2011
*/

global class CustomCloneFunctionClass {
	 private static Map<String, Schema.SObjectType> gd = Schema.getGlobalDescribe();	
	 
	 // If return null, clone fail and must alert users, else clone successfully.
	 WebService static ID CCIRCaseClone(ID cid) {
	 	ID login_uid = UserInfo.getUserId(); // log in user id
	 	Case clonedCase = (Case) cloneObj('Case', cid);
	 	setCaseFieldsToFixedvalues(clonedCase, login_uid);
	 	Database.Saveresult csr;
	 	Savepoint sp = Database.setSavepoint(); 
	 	try{
	 		csr = Database.insert(clonedCase);
	 	}catch(Exception ex){
	 		Database.rollback(sp);
	 		GeneralConstants.mailAnyExceptionToMe('CustomCloneFunctionClass', 'Clone CCIR Incident Case fail. Cid = ' + cid, ex);
	 		return null; 
	 	}
	 	ID clonedCaseId = csr.getId();
	 	list<CaseComment> clonedCaseComments = (list<CaseComment>) cloneChildObjs('CaseComment', cid, clonedCaseId);
	 	list<Attachment> clonedAttachments = (list<Attachment>) cloneChildObjs('Attachment', cid, clonedCaseId);
	 	try{
	 		insert clonedCaseComments;
	 		insert clonedAttachments;
	 	}catch(Exception ex){
	 		Database.rollback(sp);
	 		GeneralConstants.mailAnyExceptionToMe('CustomCloneFunctionClass', 'Clone CCIR Case comment/Attachment fail. Case fail. Cid = ' + cid, ex);
	 		return null; 
	 	}
	 	return clonedCaseId;
	 }

	 private static void setCaseFieldsToFixedvalues (Case c, ID login_uid){
	 	c.IR_Priority__c = 'Standard';
	 	c.Status = 'Open';
	 	c.CSS_CRF_RequestType__c = '';
	 	c.Origin = 'Internal';
	 	c.OwnerId = login_uid;	
	 	c.IsEscalated = false;
	 	c.CSS_InitialEscalationDateTime__c = null;
	 	c.SuppliedEmail = GeneralConstants.checkAndTransformWebEmail(c.SuppliedEmail); 	
	 }

	 public static Sobject cloneObj(String objName, ID objId){
	 	Sobject originalObj = queryObj(objName, objId) ; 
	    Sobject clonedObj = originalObj.clone(false, true); // clear Id, deep clone
    	return clonedObj;
	 }
	 
	 public static Sobject queryObj(String objName, ID objId){
	 	String objFields = getAllFields(objName);
    	String qryString = 'SELECT ' + objFields + ' FROM ' + objName;
		qryString = qryString + ' WHERE ' + objName + '.Id = ' + '\'' + objId + '\'' ; 
	    Sobject queriedObj = Database.query(qryString) ; 
	    return queriedObj;
	 } 
	 
	 public static List<Sobject> cloneObjs(String objName, Set<ID> objIds){
	 	List<Sobject> originalObjs = queryObjs(objName, objIds);
	    List<Sobject> clonedObjs = new List<Sobject>();
	    for(Sobject obj : originalObjs){
	    	Sobject cObj = obj.clone(false, true); // clear Id, deep clone
	    	clonedObjs.add(cObj);
	    }
    	return clonedObjs;
	 }
	 
	 public static List<Sobject> queryObjs(String objName, Set<ID> objIds){
	 	String objFields = getAllFields(objName);
	 	String newObjIds = '(';
	 	for(ID i : objIds){
	 		newObjIds += '\'' + i + '\',';
	 	}
	 	newObjIds = newObjIds.substring(0, newObjIds.lastIndexOf(',')); //trim last comma;
	 	newObjIds += ')';
    	String qryString = 'SELECT ' + objFields + ' FROM ' + objName;
		qryString = qryString + ' WHERE ' + objName + '.Id IN ' + newObjIds; 
	    List<Sobject> queriedObjs = Database.query(qryString) ;
	    return queriedObjs;
	 } 	 	
	 
	 private static String getAllFields(String objName){
	 	Schema.SObjectType obj = gd.get(objName) ;
    	Map<String, Schema.SObjectField> M = obj.getDescribe().fields.getMap() ;
    	String objAllFields = '';
    	for (Schema.SObjectField field : M.values()){
    		Schema.DescribeFieldResult descibe = field.getDescribe();
    		String fieldname = descibe.getName();
    		objAllFields += fieldname + ',';
    	}
    	objAllFields = objAllFields.substring(0, objAllFields.lastIndexOf(',')); //trim last comma;
    	return objAllFields;
	 }
	 	  
	 private static list<Sobject> cloneChildObjs(String objName, ID oldPid, ID newPid){
	 	String objFields = getAllFields(objName);
    	String qryString = 'SELECT ' + objFields + ' FROM ' + objName;
		qryString = qryString + ' WHERE ' + objName + '.ParentId = ' + '\'' + oldPid + '\'' ; 
	    list<Sobject> originaChildlObjs = Database.query(qryString) ; 
	    list<Sobject> clonedchildObjs = originaChildlObjs.deepClone(false); // clear Id, deep clone
	    for(Sobject obj : clonedchildObjs){
	    	obj.put('ParentId', newPid);
	    }
	 	return clonedchildObjs;
	 }
	 
	 WebService static String TransferToNationalCase(ID cid, ID rId, ID qId, String s) {
	 	String err = '';
	 	Case c = [select id from Case where Id =: cid];
	 	if(c != null){
	 		c.RecordTypeId = rId;
	 		c.OwnerId = qId;
	 		c.Status = s;
	 		c.AccountId = null;
	 		try{
	 			update c;
	 		}catch(Exception ex){
	 			err = ex.getMessage();
	 		}
	 	}else{
	 		err = ' Case not found!';
	 	}
	 	return err;
	 }
}